package com.github.mikephil.charting.custom.radarchart;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.RectF;
import android.util.AttributeSet;

import com.github.mikephil.charting.charts.PieRadarChartBase;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.components.YAxis.AxisDependency;
import com.github.mikephil.charting.utils.Utils;

/**
 * 自定义雷达图
 *
 * @author Created by wanggaowan on 3/18/21 1:36 PM
 */
public class SmartRadarChart extends PieRadarChartBase<SmartRadarData> {
    /**
     * width of the main web lines
     */
    private float mWebLineWidth = 2.5f;
    
    /**
     * width of the inner web lines
     */
    private float mInnerWebLineWidth = 1.5f;
    
    /**
     * color for the main web lines
     */
    private int mWebColor = Color.rgb(122, 122, 122);
    
    /**
     * color for the inner web
     */
    private int mWebColorInner = Color.rgb(122, 122, 122);
    
    /**
     * transparency the grid is drawn with (0-255)
     */
    private int mWebAlpha = 150;
    
    /**
     * flag indicating if the web lines should be drawn or not
     */
    private boolean mDrawWeb = true;
    
    /**
     * modulus that determines how many labels and web-lines are skipped before the next is drawn
     */
    private int mSkipWebLineCount = 0;
    
    /**
     * the object reprsenting the y-axis labels
     */
    private YAxis mYAxis;
    
    protected YAxisRendererSmartRadarChart mYAxisRenderer;
    protected XAxisRendererSmartRadarChart mXAxisRenderer;
    
    public SmartRadarChart(Context context) {
        super(context);
    }
    
    public SmartRadarChart(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    
    public SmartRadarChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }
    
    @Override
    protected void init() {
        super.init();
        
        mYAxis = new YAxis(AxisDependency.LEFT);
        
        mWebLineWidth = Utils.convertDpToPixel(1.5f);
        mInnerWebLineWidth = Utils.convertDpToPixel(0.75f);
        
        mRenderer = new SmartRadarChartRenderer(this, mAnimator, mViewPortHandler);
        mYAxisRenderer = new YAxisRendererSmartRadarChart(mViewPortHandler, mYAxis, this);
        mXAxisRenderer = new XAxisRendererSmartRadarChart(mViewPortHandler, mXAxis, this);
        
        mHighlighter = new SmartRadarHighlighter(this);
    }
    
    @Override
    protected void calcMinMax() {
        super.calcMinMax();
        
        mYAxis.calculate(mData.getYMin(AxisDependency.LEFT), mData.getYMax(AxisDependency.LEFT));
        mXAxis.calculate(0, mData.getMaxEntryCountSet().getEntryCount());
    }
    
    @Override
    public void notifyDataSetChanged() {
        if (mData == null)
            return;
        
        calcMinMax();
        
        mYAxisRenderer.computeAxis(mYAxis.mAxisMinimum, mYAxis.mAxisMaximum, mYAxis.isInverted());
        mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false);
        
        if (mLegend != null && !mLegend.isLegendCustom())
            mLegendRenderer.computeLegend(mData);
        
        calculateOffsets();
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        
        if (mData == null)
            return;
        
        if (mXAxis.isEnabled())
            mXAxisRenderer.computeAxis(mXAxis.mAxisMinimum, mXAxis.mAxisMaximum, false);
        
        mXAxisRenderer.renderAxisLabels(canvas);
        
        if (mDrawWeb)
            mRenderer.drawExtras(canvas);
        
        if (mYAxis.isEnabled() && mYAxis.isDrawLimitLinesBehindDataEnabled())
            mYAxisRenderer.renderLimitLines(canvas);
        
        mRenderer.drawData(canvas);
        
        if (valuesToHighlight())
            mRenderer.drawHighlighted(canvas, mIndicesToHighlight);
        
        if (mYAxis.isEnabled() && !mYAxis.isDrawLimitLinesBehindDataEnabled())
            mYAxisRenderer.renderLimitLines(canvas);
        
        mYAxisRenderer.renderAxisLabels(canvas);
        
        mRenderer.drawValues(canvas);
        
        mLegendRenderer.renderLegend(canvas);
        
        drawDescription(canvas);
        
        drawMarkers(canvas);
    }
    
    /**
     * Returns the factor that is needed to transform values into pixels.
     */
    public float getFactor() {
        RectF content = mViewPortHandler.getContentRect();
        return Math.min(content.width() / 2f, content.height() / 2f) / mYAxis.mAxisRange;
    }
    
    /**
     * Returns the angle that each slice in the radar chart occupies.
     */
    public float getSliceAngle() {
        return 360f / (float) mData.getMaxEntryCountSet().getEntryCount();
    }
    
    @Override
    public int getIndexForAngle(float angle) {
        
        // take the current angle of the chart into consideration
        float a = Utils.getNormalizedAngle(angle - getRotationAngle());
        
        float sliceangle = getSliceAngle();
        
        int max = mData.getMaxEntryCountSet().getEntryCount();
        
        int index = 0;
        
        for (int i = 0; i < max; i++) {
            
            float referenceAngle = sliceangle * (i + 1) - sliceangle / 2f;
            
            if (referenceAngle > a) {
                index = i;
                break;
            }
        }
        
        return index;
    }
    
    /**
     * Returns the object that represents all y-labels of the RadarChart.
     */
    public YAxis getYAxis() {
        return mYAxis;
    }
    
    /**
     * Sets the width of the web lines that come from the center.
     */
    public void setWebLineWidth(float width) {
        mWebLineWidth = Utils.convertDpToPixel(width);
    }
    
    public float getWebLineWidth() {
        return mWebLineWidth;
    }
    
    /**
     * Sets the width of the web lines that are in between the lines coming from
     * the center.
     */
    public void setWebLineWidthInner(float width) {
        mInnerWebLineWidth = Utils.convertDpToPixel(width);
    }
    
    public float getWebLineWidthInner() {
        return mInnerWebLineWidth;
    }
    
    /**
     * Sets the transparency (alpha) value for all web lines, default: 150, 255
     * = 100% opaque, 0 = 100% transparent
     */
    public void setWebAlpha(int alpha) {
        mWebAlpha = alpha;
    }
    
    /**
     * Returns the alpha value for all web lines.
     */
    public int getWebAlpha() {
        return mWebAlpha;
    }
    
    /**
     * Sets the color for the web lines that come from the center. Don't forget
     * to use getResources().getColor(...) when loading a color from the
     * resources. Default: Color.rgb(122, 122, 122)
     */
    public void setWebColor(int color) {
        mWebColor = color;
    }
    
    public int getWebColor() {
        return mWebColor;
    }
    
    /**
     * Sets the color for the web lines in between the lines that come from the
     * center. Don't forget to use getResources().getColor(...) when loading a
     * color from the resources. Default: Color.rgb(122, 122, 122)
     */
    public void setWebColorInner(int color) {
        mWebColorInner = color;
    }
    
    public int getWebColorInner() {
        return mWebColorInner;
    }
    
    /**
     * If set to true, drawing the web is enabled, if set to false, drawing the
     * whole web is disabled. Default: true
     */
    public void setDrawWeb(boolean enabled) {
        mDrawWeb = enabled;
    }
    
    /**
     * Sets the number of web-lines that should be skipped on chart web before the
     * next one is drawn. This targets the lines that come from the center of the RadarChart.
     *
     * @param count if count = 1 -> 1 line is skipped in between
     */
    public void setSkipWebLineCount(int count) {
        
        mSkipWebLineCount = Math.max(0, count);
    }
    
    /**
     * Returns the modulus that is used for skipping web-lines.
     */
    public int getSkipWebLineCount() {
        return mSkipWebLineCount;
    }
    
    @Override
    protected float getRequiredLegendOffset() {
        return mLegendRenderer.getLabelPaint().getTextSize() * 4.f;
    }
    
    @Override
    protected float getRequiredBaseOffset() {
        return mXAxis.isEnabled() && mXAxis.isDrawLabelsEnabled() ?
            mXAxis.mLabelRotatedWidth :
            Utils.convertDpToPixel(10f);
    }
    
    @Override
    public float getRadius() {
        RectF content = mViewPortHandler.getContentRect();
        return Math.min(content.width() / 2f, content.height() / 2f);
    }
    
    /**
     * Returns the maximum value this chart can display on it's y-axis.
     */
    public float getYChartMax() {
        return mYAxis.mAxisMaximum;
    }
    
    /**
     * Returns the minimum value this chart can display on it's y-axis.
     */
    public float getYChartMin() {
        return mYAxis.mAxisMinimum;
    }
    
    /**
     * Returns the range of y-values this chart can display.
     */
    public float getYRange() {
        return mYAxis.mAxisRange;
    }
}
